home *** CD-ROM | disk | FTP | other *** search
- /*
- * NAME
- * gdevretina.c
- *
- * DESCRIPTION
- * GhostScript device-driver for the Macro-Systems
- * RETINA graphics board. Currently this driver does not work
- * with 16-Bit Color-Lookup-Tables
- *
- * LEGAL STATUS
- * GNUware
- *
- * AUTHOR
- * Andreas Heitmann
- *
- * EMAIL
- * andreas@gotcha.swb.de
- * ah@hrz.uni-kassel.de
- * ah@rbg.informatik.th-darmstadt.de
- *
- */
- #include <stdio.h>
- #include <string.h>
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <exec/libraries.h>
- #include <graphics/gfx.h>
- #include <retina/retina.h>
- #include <retina/clib/retina_protos.h>
- #include "gs.h"
- #include "gxdevice.h"
- #include "gdevretina.h"
- #include "gsmatrix.h"
- #include <stdlib.h>
-
- #define X_DPI 72
- #define Y_DPI 72
-
- #define RETINA_LIB_VERSION 3
-
- #if RETINA_LIB_VERSION<4
- #define FILLRECTHACK
- #endif
-
- #define COPYMONOHACK
-
- #ifdef COPYMONOHACK
- #define RETINA_COPY_MONO r_copy_mono
- #else
- #define RETINA_COPY_MONO r_fast_copy_mono
- #endif
-
- void TEST(char *x)
- {
- char test[3];
- eprintf(x);
- eprintf("\n");
- fflush(stderr);
- fgets(test,2,stdin);
- }
-
- /* forward declarations */
- dev_proc_open_device(r_open_device);
- dev_proc_close_device(r_close_device);
- dev_proc_map_rgb_color(r_map_rgb_color_8_16);
- dev_proc_map_color_rgb(r_map_color_rgb_8_16);
- dev_proc_map_rgb_color(r_map_rgb_color_24);
- dev_proc_map_color_rgb(r_map_color_rgb_24);
- dev_proc_fill_rectangle(r_fill_rectangle);
- dev_proc_copy_mono(RETINA_COPY_MONO);
- dev_proc_copy_color(r_copy_color);
- dev_proc_draw_line(r_draw_line);
- dev_proc_get_initial_matrix(r_get_initial_matrix);
-
- #define retina_procs_24 { r_open_device, r_get_initial_matrix, gx_default_sync_output, gx_default_output_page, r_close_device, r_map_rgb_color_24, r_map_color_rgb_24, r_fill_rectangle, gx_default_tile_rectangle, RETINA_COPY_MONO, r_copy_color, r_draw_line, gx_default_get_bits, gx_default_get_props, gx_default_put_props }
- #define retina_procs_16 { r_open_device, r_get_initial_matrix, gx_default_sync_output, gx_default_output_page, r_close_device, r_map_rgb_color_8_16, r_map_color_rgb_8_16, r_fill_rectangle, gx_default_tile_rectangle, RETINA_COPY_MONO, r_copy_color, r_draw_line, gx_default_get_bits, gx_default_get_props, gx_default_put_props }
- #define retina_procs_8 { r_open_device, r_get_initial_matrix, gx_default_sync_output, gx_default_output_page, r_close_device, r_map_rgb_color_8_16, r_map_color_rgb_8_16 , r_fill_rectangle, gx_default_tile_rectangle, RETINA_COPY_MONO, r_copy_color, r_draw_line, gx_default_get_bits, gx_default_get_props, gx_default_put_props }
-
- private gx_device_procs gs_retina_procs_8 = retina_procs_8;
- private gx_device_procs gs_retina_procs_16 = retina_procs_16;
- private gx_device_procs gs_retina_procs_24 = retina_procs_24;
-
- #define gs_retina_skel(procs,name,colors,mode) {sizeof(retina_device),&procs,name,0,0,XPPI,YPPI,no_margins,colors,FALSE,NULL,mode,0,NULL,NULL,NULL}
-
- retina_device gs_retina8_device = gs_retina_skel(gs_retina_procs_8, "retina8" ,dci_color( 8, 31, 4),MID_DEFAULT_08);
- retina_device gs_retina16_device = gs_retina_skel(gs_retina_procs_16,"retina16",dci_color(16,255,256),MID_DEFAULT_16);
- retina_device gs_retina24_device = gs_retina_skel(gs_retina_procs_24,"retina24",dci_color(24,255,256),MID_DEFAULT_24);
-
- /** procedures **/
-
- /* tests if the pixel coordinates have valid values */
- static boolean
- retina_is_valid_area(gx_device * dev, int x, int y, int width, int height)
- {
- return x >= 0 && y >= 0 && x + width <= rdev->width && y + height <= rdev->height;
- }
-
- /* Amiga library bases */
- struct RetinaBase *RetinaBase = NULL;
- struct GfxBase *GfxBase = NULL;
-
-
- void
- gs_retina_setrgb(gx_device *dev,byte r,byte g,byte b)
- {
- rdev->palette[rdev->ncols][0]=r;
- rdev->palette[rdev->ncols][1]=g;
- rdev->palette[rdev->ncols][2]=b;
- rdev->ncols++;
- }
-
- /*
- * preallocate colors for video-modes with color-lookup tables
- */
- int
- preallocate_colors(gx_device *dev)
- {
- int res=0;
-
- switch (rdev->screenmode) {
- case MID_DEFAULT_08:
- case MID_DEFAULT_16:
- rdev->palette =(byte (*)[3])calloc(1 << dev->color_info.depth, 3*sizeof(byte));
- if (NULL != rdev->palette) {
- gx_color_index color;
- byte r, g, b;
-
- /* reset index counter */
- rdev->ncols = 0;
-
- /* allocate black & white as first 2 colors */
- gs_retina_setrgb(dev,0, 0, 0);
- gs_retina_setrgb(dev,255, 255, 255);
-
- /* allocate evenly space color cube */
- while (rdev->ncols < RGB_COLS) {
- color = rdev->ncols - 1;
- r = ((color & RED_MASK) >> (GREEN_BITS + BLUE_BITS))
- * ((1 << dev->color_info.depth) - 1) / (RED_COLS - 1);
- g = ((color&GREEN_MASK) >> BLUE_BITS)
- * ((1 << dev->color_info.depth) - 1) / (GREEN_COLS - 1);
- b = (color&BLUE_MASK)
- * ((1 << dev->color_info.depth) - 1) / (RED_COLS - 1);
- /* Retina_SetPalette(rdev->rs,rdev->ncols,r,g,b); */
- gs_retina_setrgb(dev,r,g,b);
- }
-
- /* load the color map */
- Retina_LoadPalette(rdev->rs, 0, rdev->ncols, (UBYTE *) rdev->palette);
- }
- else {
- eprintf("gs retina: no memory for colormap\n");
- res = -1;
- }
- break;
- default:
- }
- return res;
- }
-
- int
- open_screen(gx_device *dev)
- {
- int res=0;
-
- if(NULL!=(GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0))) {
- if(NULL!=(RetinaBase=(struct RetinaBase *)OpenLibrary
- ("retina.library",RETINA_LIB_VERSION))) {
- if (NULL !=(rdev->rs = Retina_OpenScreen(
- rdev->width == 0 ? RSCR_MAXWIDTH : rdev->width,
- rdev->height == 0 ? RSCR_MAXHEIGHT : rdev->height,
- rdev->screenmode,
- RSFF_AUTOADJUST | RSFF_DONTCLEARONOPEN | RSFF_DONTCLEARONCLOSE,
- NULL))) {
- Retina_ClearScreen(rdev->rs);
- /*
- * real screensize may have changed due to memory lack, so correct the
- * variables
- */
- rdev->width = rdev->rs->_rs_Width;
- rdev->height = rdev->rs->_rs_Height;
- }
- else {
- eprintf("gs retina: can't open retina screen.\n");
- res = -1;
- }
- }
- else {
- res = -1;
- eprintf1("gs retina: can't open version %d of the retina.library.\n",
- RETINA_LIB_VERSION);
- }
- }
- else {
- res = -1;
- eprintf("gs retina: can't open graphics library.\n");
- }
- return res;
- }
-
- void
- setup_rdev(gx_device *dev)
- {
- rdev->wz_scale_x = (float)rdev->width / PRE_WIDTH;
- rdev->wz_scale_y = (float)rdev->height / PRE_HEIGHT;
- rdev->is_open = TRUE;
- }
-
- int
- r_open_device(gx_device *dev)
- {
- int res=0;
- char buf[3];
-
- rdev->is_open=FALSE;
- rdev->rs=NULL;
- if(0==(res=open_screen(dev))) {
- preallocate_colors(dev);
- setup_rdev(dev);
- }
- return res;
- }
-
- /*
- * closes retina device
- * - close screen
- * - close library
- */
- int
- r_close_device(gx_device * dev)
- {
- /*
- * free color palette, if allocated
- */
- switch (rdev->screenmode) {
- case MID_DEFAULT_08:
- case MID_DEFAULT_16:
- if (rdev->palette != NULL) free(rdev->palette);
- break;
- case MID_DEFAULT_24:
- break;
- }
-
- /*
- * close screen, if opened
- */
- if (rdev->rs != NULL) {
- Retina_CloseScreen(rdev->rs);
- rdev->is_open = FALSE;
- }
-
- /*
- * close libraries
- */
- if (RetinaBase != NULL) CloseLibrary((struct Library *)RetinaBase);
- if (GfxBase != NULL) CloseLibrary((struct Library *)GfxBase);
-
- /*
- * exit without error
- */
- return 0;
- }
-
- /*
- * modified sun mapping routines
- */
- gx_color_index
- r_map_rgb_color_24(gx_device * dev, gx_color_value r, gx_color_value g, gx_color_value b)
- {
- return
- (gx_color_value_to_byte(r)<<16)+
- (gx_color_value_to_byte(g)<<8)+
- gx_color_value_to_byte(b);
- }
-
- gx_color_index
- r_map_rgb_color_8_16(gx_device * dev, gx_color_value r, gx_color_value g, gx_color_value b)
- {
- gx_color_index ret = gx_no_color_index;
- byte red_val, green_val, blue_val;
- gx_color_index i;
- static int warn = 1;
-
- /*
- * Determine the RGB values at display resolution we ideally would want
- * this color to be mapped into.
- */
- red_val =gx_color_value_to_byte(r);
- green_val=gx_color_value_to_byte(g);
- blue_val =gx_color_value_to_byte(b);
-
- /*
- * Look for an exact match among the colors already allocated. This
- * includes the pre-allocated default color cube.
- */
- for (i = 0; i < rdev->ncols; i++) {
- if (rdev->palette[i][0] == red_val &&
- rdev->palette[i][1] == green_val &&
- rdev->palette[i][2] == blue_val) {
- ret = i;
- }
- }
- if (ret == gx_no_color_index) {
- if (rdev->ncols == (1 << dev->color_info.depth)) {
- if (warn) {
- eprintf("gs retina: last spare color map entry allocated\n");
- warn = 0;
- }
- }
- else {
- Retina_SetPalette(rdev->rs, i, red_val, green_val, blue_val);
- gs_retina_setrgb(dev,red_val, green_val, blue_val);
- ret = i;
- } /* else alloc new color */
- } /* end if no spare colors */
- return ret;
- }
-
- /*
- * map retina color index to ghostscript rgb-value
- */
- int
- r_map_color_rgb_24(gx_device * dev, gx_color_index color, ushort prgb[3])
- {
- prgb[0]=gx_color_value_from_byte((color>>16)&0xff);
- prgb[1]=gx_color_value_from_byte((color>> 8)&0xff);
- prgb[2]=gx_color_value_from_byte( color &0xff);
- return 0;
- }
-
- int
- r_map_color_rgb_8_16(gx_device * dev, gx_color_index color, ushort prgb[3])
- {
- prgb[0]=gx_color_value_from_byte(rdev->palette[color][0]);
- prgb[1]=gx_color_value_from_byte(rdev->palette[color][1]);
- prgb[2]=gx_color_value_from_byte(rdev->palette[color][2]);
- return 0;
- }
-
- /*
- * fill rectangle with color
- */
- int
- r_fill_rectangle(gx_device * dev, int x, int y, \
- int width, int height, gx_color_index color)
- {
- int res = 0;
-
- if (retina_is_valid_area(dev, x, y, width, height)) {
- #ifdef FILLRECTHACK
- switch (rdev->screenmode) {
- case MID_DEFAULT_24:
- #endif
- Retina_SetDrMd(rdev->rs, RDM_JAM1);
- Retina_SetAPen(rdev->rs, color);
- Retina_RectFill(rdev->rs, x, y, x + width, y + height);
- #ifdef FILLRECTHACK
- break;
- /*
- * There is a bug in the RectFill routine of retina.library version 2.3
- * in the 8 & 16 Bit color-mode so i can't use it.
- *
- * This bug has been fixed in Version 3.8 of retina.library
- */
- case MID_DEFAULT_08:
- case MID_DEFAULT_16:
- {
- int xx;
-
- Retina_SetDrMd(rdev->rs, RDM_JAM1);
- Retina_SetAPen(rdev->rs, color);
- for (xx = x + width - 1; xx >= x; xx--)
- Retina_Line(rdev->rs, xx, y, xx, y + height - 1);
- break;
- }
- }
- #endif
- }
- else res = -1;
- return res;
- }
-
- /*
- * draw line
- */
- int
- r_draw_line(gx_device * dev, int x0, int y0, int x1, int y1, \
- gx_color_index color)
- {
- int h;
-
- if (!(y1 == y0 && x1 == x0)) {
- Retina_SetDrMd(rdev->rs, RDM_JAM1);
- Retina_SetAPen(rdev->rs, color);
- Retina_Line(rdev->rs, x0, y0, x1, y1);
- }
- return 0;
- }
-
- #ifdef COPYMONOHACK
- int r_copy_mono
- (gx_device *dev,\
- const unsigned char *data, int data_x, int raster, gx_bitmap_id id,\
- int x, int y, int width, int height,\
- gx_color_index color0, gx_color_index color1)
- {
- boolean draw = TRUE;
- int res = 0;
- unsigned char *dp; /* pointer to first byte of each line */
- static gx_bitmap_id old_id = gx_no_bitmap_id;
- unsigned char bit; /* bitmask */
- long byte; /* byte number in scanline */
- gx_color_index color; /* actual color: color_c */
- long ix, iy; /* coordinates in data space */
- int c; /* color index: 0..1 */
-
- /*
- * this is a hack and has to be replaced in future versions of gdevretina.c
- *
- * i am trying to replace this by a bitmap-copy but not before the
- * next release of the retina-software
- */
- if (retina_is_valid_area(dev, x, y, width, height)) {
- for (c = 0; c <= 1; c++) {
- color = (c == 0) ? color0 : color1;
- if (color != gx_no_color_index) {
- dp = data;
- for (iy = 0; iy < height; iy++) {
- for (byte = 0, ix = 0; ix < width; byte++) {
- for (bit = 1 << 7; bit && ix < width; ix++, bit >>= 1) {
- if (dp[byte] & bit)
- Retina_SetPixel(rdev->rs, x + ix, y + iy, color);
- }
- }
- dp += raster;
- }
- }
- }
- }
- else res = -1;
- return res;
- }
- #endif
-
- /*
- * The following function is a replacement for the slow r_copy_mono routine.
- * It still doesn't work because Retina_WriteBitMap doesn't support
- * writing WBMMODE_STD BitMaps to 24Bit Screens.
- * If the bug is fixed in newer versions of the retina.library i will
- * undefine COPYMONOHACK :)
- */
- #ifndef COPYMONOHACK
- int
- r_fast_copy_mono(gx_device * dev, unsigned char *data, int data_x, \
- int raster, gx_bitmap_id id, int x, int y, \
- int width, int height, gx_color_index color0, \
- gx_color_index color1)
- {
- unsigned char pal[2 * 3];
- static struct BitMap mybm;
- int res = 0;
-
- if (retina_is_valid_area(dev, x, y, width, height)) {
- InitBitMap(&mybm, 1, width, height);
- #ifdef DEBUG
- printf("bm.bbr=%d\n", mybm.BytesPerRow);
- printf("bm.row=%d\n", mybm.Rows);
- printf("bm.flg=%d\n", mybm.Flags);
- printf("bm.dpt=%d\n", mybm.Depth);
- printf("x=%d y=%d w=%d h=%d raster=%d\n", x, y, width, height, raster);
- #endif
- /*
- * correct the number of bytes per row, because gfx has it's own way to
- * compute the number of bytes from the number of pixels in each line.
- */
- mybm.BytesPerRow = raster;
- mybm.Planes[0] = (PLANEPTR) data;
- #ifdef DEBUG
- {
- int i, j;
-
- for (j = 0; j < height; j++) {
- for (i = 0; i < raster; i++) {
- printf("%02x ", *(mybm.Planes[0] + i + j * raster));
- }
- puts("");
- }
- }
- #endif
- pal[0] = ((unsigned char *)&color0)[1];
- pal[1] = ((unsigned char *)&color0)[2];
- pal[2] = ((unsigned char *)&color0)[3];
- pal[3] = ((unsigned char *)&color1)[1];
- pal[4] = ((unsigned char *)&color1)[2];
- pal[5] = ((unsigned char *)&color1)[3];
- Retina_WriteBitMap(rdev->rs, &mybm, pal, x, y, width, WBMMODE_STD);
- }
- else
- res = -1;
- return res;
- }
- #endif
-
- int
- r_copy_color(
- gx_device *dev,\
- const unsigned char *data, int data_x, int raster, gx_bitmap_id id,\
- int x, int y, int width, int height)
- {
- int res = 0;
-
- if (retina_is_valid_area(dev, x, y, width, height)) {
- switch (rdev->screenmode) {
- case MID_DEFAULT_24:
- Retina_WriteRect(data, 0, 0, raster, RECTMODE_RGB, rdev->rs, x, y, width,
- height, NULL);
- break;
- case MID_DEFAULT_08:
- Retina_WriteRect(data, 0, 0, raster, RECTMODE_256, rdev->rs, x, y, width,
- height, NULL);
- break;
- }
- }
- else
- res = -1;
- return res;
- }
-
- void
- r_get_initial_matrix(gx_device * dev, gs_matrix * m)
- {
- /* scale the user coordinates with SCALE */
- m->xy = m->yx = m->tx = 0;
- m->xx = rdev->x_pixels_per_inch * SCALE * rdev->wz_scale_x /X_DPI;
- m->yy = -rdev->y_pixels_per_inch * SCALE * rdev->wz_scale_y/Y_DPI;
- m->ty = rdev->height;
- }
-